package com.tiamosu.databinding.delegate

import android.view.View
import androidx.activity.ComponentActivity
import androidx.annotation.RestrictTo
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.LifecycleOwner
import androidx.viewbinding.ViewBinding
import com.tiamosu.databinding.internal.findRootView

/**
 * Create new [ViewBinding] associated with the [ComponentActivity] and allow customize how
 * a [View] will be bounded to the view binding.
 */
fun <A : ComponentActivity, T : ViewBinding> lazyDataBindingOrNull(
    onViewDestroyed: (T) -> Unit = {}
): ViewBindingPropertyOrNull<A, T?> {
    return lazyDataBindingOrNull({ activity: A ->
        checkNotNull(DataBindingUtil.bind(activity.findRootView()) as? T) {
            "dataBinding must no be null"
        }
    }, onViewDestroyed)
}

fun <A : ComponentActivity, T : ViewBinding> lazyDataBindingOrNull(
    viewBinder: (A) -> T,
    onViewDestroyed: (T) -> Unit = {},
): ViewBindingPropertyOrNull<A, T?> {
    return activityViewBindingOrNull(viewBinder, onViewDestroyed)
}

@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
private fun <A : ComponentActivity, T : ViewBinding> activityViewBindingOrNull(
    viewBinder: (A) -> T,
    onViewDestroyed: (T) -> Unit = {},
    viewNeedInitialization: Boolean = true
): ViewBindingPropertyOrNull<A, T?> {
    return ActivityViewBindingPropertyOrNull(onViewDestroyed, viewNeedInitialization, viewBinder)
}

@RestrictTo(RestrictTo.Scope.LIBRARY)
private class ActivityViewBindingPropertyOrNull<in A : ComponentActivity, out T : ViewBinding>(
    onViewDestroyed: (T) -> Unit,
    private val viewNeedInitialization: Boolean = true,
    viewBinder: (A) -> T
) : LifecycleViewBindingPropertyOrNull<A, T>(viewBinder, onViewDestroyed) {

    override fun getLifecycleOwner(thisRef: A): LifecycleOwner {
        return thisRef
    }

    override fun isViewInitialized(thisRef: A): Boolean {
        return viewNeedInitialization && thisRef.window != null
    }
}